iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 14
2
DevOps

用 CDK 定義 AWS 架構系列 第 14

Day 14 - 使用 CDK 控制 Elastic Load Balancing - Application Load Balancer

  • 分享至 

  • xImage
  •  

說到部署機器怎麼可以少了 Load Balancing (LB) 呢?今天就來介紹 LB 吧!

https://ithelp.ithome.com.tw/upload/images/20200930/20117701GtFoof8DD0.jpg

在 CDK 的文件上面都是建議使用 Auto Scaling Group (ASG) 來設定,因為這樣才是一個高可用性架構,不過我覺得可以從單獨一個服務開始說起,畢竟單獨解釋一個服務會比較好理解,況且我知道很多公司的服務其實一台機器就可以頂住了 XD

建立 Load Balancing

建立 ALB

這次新增了一個新的 package 是 @aws-cdk/aws-elasticloadbalancingv2 它用來處理 Elastic Load Balancing
internetFacing 預設是 false,意思是創建一個內網的 Load Balancing 而我們這邊目前需要的是外網的所以要把它設定成 true
使用 CfnOutput 把 Load Balancing 的 DNS 印出來

import * as elbv2 from "@aws-cdk/aws-elasticloadbalancingv2";

const alb = new elbv2.ApplicationLoadBalancer(this, "ALB", {
  vpc,
  internetFacing: true,
});
new cdk.CfnOutput(this, "LoadBalancerDNS", {
  value: alb.loadBalancerDnsName,
});

新增 Listener

目前只有一個 Listener 使用 port 80,因為目前的服務是要給 HTTP 的

const listener = alb.addListener("Listener", {
  port: 80,
  open: true,
});

新增 Target 到 Listener

以昨天的服務來說我們有一個 /phpinfo.php 目前先用它來做 healthCheck 頁面之後會再修正它,用這個頁面來做其實不太正確不過就先頂著用吧 XD
另外加入 ec2Instance 當我們的 Target,如此設定就可以讓我們的 ALB 後面有一個 Target Group 而裡面有一台 ec2Instance 了
這邊需要注意一下我們的 targets 要使用 aws-elasticloadbalancingv2-targets package 來作為我們的 targets,因為 elbv2.InstanceTarget 要棄用了,所以不要使用 new elbv2.InstanceTarget(ec2Instance.instanceId) 呦!

import * as targets from "@aws-cdk/aws-elasticloadbalancingv2-targets";

listener.addTargets("Targets", {
  healthCheck: {
    enabled: true,
    path: "/phpinfo.php",
  },
  port: 80,
  targets: [new targets.InstanceTarget(ec2Instance)],
});

新增 Security Group

這邊需要注意一下預設的 ALB 會把 outbound 完全丟掉,所以需要特別新增 listener 到 EC2 的 Security Group

listener.connections.allowTo(ec2Instance, ec2.Port.tcp(httpPort));

ALB Security Group 如何限制 outbound

在閱讀 CDK Source Code 的時候發現一個很有趣的東西如果要阻止所有流量的時候會建立一條規則

  • IP: 255.255.255.255/32 - 實際上沒有任何機器可以擁有此 IP
  • Protocol: ICMP
  • Port 252 - 實際上沒有定義的 Type

可以查看 Wiki 網際網路控制訊息協定

const MATCH_NO_TRAFFIC = {
  cidrIp: '255.255.255.255/32',
  description: 'Disallow all traffic',
  ipProtocol: 'icmp',
  fromPort: 252,
  toPort: 86,
};

https://github.com/aws/aws-cdk/blob/v1.64.1/packages/@aws-cdk/aws-ec2/lib/security-group.ts##L508-L523

整理一遍整個服務的 Code

最後我們一樣把整個 Source Code 整理一次給大家,讓大家方便好部署 XD

const vpc = new ec2.Vpc(this, "VPC", {
  maxAzs: 3,
  natGateways: 0,
});

// 設定 Security Group
const mySecurityGroup = new ec2.SecurityGroup(this, "SecurityGroup", {
  vpc,
  allowAllOutbound: true,
});
mySecurityGroup.addIngressRule(
  ec2.Peer.anyIpv4(),
  ec2.Port.tcp(22),
  "allow public ssh access"
);

// 設定上傳的 User Data 腳本
const asset = new assets.Asset(this, "Asset", {
  path: path.join(__dirname, "../", "ec2-config", "configure.sh"),
});

// 設定 EC2 機器
const ec2Instance = new ec2.Instance(this, "Instance", {
  vpc,
  instanceType: ec2.InstanceType.of(
    ec2.InstanceClass.T3,
    ec2.InstanceSize.NANO
  ),
  machineImage: ec2.MachineImage.latestAmazonLinux({
    generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2,
  }),
  securityGroup: mySecurityGroup,
  vpcSubnets: {
    subnetType: ec2.SubnetType.PUBLIC,
  },
  keyName: "Clarence_KeyPair",
});
new cdk.CfnOutput(this, "EC2PublicDns", {
  value: ec2Instance.instancePublicDnsName,
});
new cdk.CfnOutput(this, "EC2PublicIp", {
  value: ec2Instance.instancePublicIp,
});

const localPath = ec2Instance.userData.addS3DownloadCommand({
  bucket: asset.bucket,
  bucketKey: asset.s3ObjectKey,
});
ec2Instance.userData.addExecuteFileCommand({
  filePath: localPath,
  arguments: "--verbose -y",
});
asset.grantRead(ec2Instance.role);

// 設定 Load Balancer
const httpPort = 80;
const alb = new elbv2.ApplicationLoadBalancer(this, "ALB", {
  vpc,
  internetFacing: true,
});
new cdk.CfnOutput(this, "LoadBalancerDNS", {
  value: alb.loadBalancerDnsName,
});

const listener = alb.addListener("Listener", {
  port: httpPort,
  open: true,
});
listener.connections.allowTo(ec2Instance, ec2.Port.tcp(httpPort));

listener.addTargets("Targets", {
  healthCheck: {
    enabled: true,
    path: "/phpinfo.php",
  },
  port: httpPort,
  targets: [new targets.InstanceTarget(ec2Instance)],
});

測試 ALB 網址

我目前拿到的

測試 Test Page

打開它試試看
https://ithelp.ithome.com.tw/upload/images/20200927/20117701n9hbrNUmIH.png

測試 phpinfo.php

http://cdkec-albae-1qhysttihzwc-231561288.us-west-2.elb.amazonaws.com/phpinfo.php

https://ithelp.ithome.com.tw/upload/images/20200927/20117701Jy0wVjDCNf.png

結論

以上是今天的 ALB 介紹希望有幫助到大家,話說我有在網路上找了找好像目前沒有人寫過單一台 Instance 接在 ALB 後面的文,今天就介紹給大家啦!

想要看更多嗎?歡迎到我的部落格參觀

文章內容主要是網路或是程式開發類型的文章

本文同步刊載於 Clarence 部落格:Day 14 - 使用 CDK 控制 Elastic Load Balancing - Application Load Balancer


「AWS CDK 完全學習手冊:打造雲端基礎架構程式碼 IaC」
本書改編並延伸自第 12 屆 iT 邦幫忙鐵人賽獲得 DevOps 組冠軍的《用 CDK 定義 AWS 架構》系列文章,以簡單、好讀的行文風格詳述技術細節,並提供完整的程式碼範例與說明,一步一步帶領新手從零開始踏上 AWS CDK 技術達人之路。

有興趣的朋友歡迎至天瓏書局選購!

購書連結 https://bit.ly/2ZMAebE

https://ithelp.ithome.com.tw/upload/images/20211103/20117701W7l6fQnn2L.jpg


上一篇
Day 13 - 使用 CDK 部署 EC2 讓 User Data 與 S3 結合我的機器也要自動部署!
下一篇
Day 15 - 使用 CDK 控制 Elastic Load Balancing - Network Load Balancer
系列文
用 CDK 定義 AWS 架構30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言